package com.example.lesson_10_25.JAVAHW.H1127;

/**
 * @PACKAGE_NAME: com.example.lesson_10_25.JAVAHW.H1127
 * @NAME: myMAP
 * @USER: jiang000
 * @DATE: 2023/11/27
 **/
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

public class myMAP<K, V> {

    private static int VALUE = 1000000;

    private static int POTRION = 500000;

    private List<Entry<K, V>>[] buckets;
    private int size;

    public myMAP() {
        this(1000000);
    }

    public myMAP(int capacity) {
        buckets = new LinkedList[capacity];
        for (int i = 0; i < capacity; i++) {
            buckets[i] = new LinkedList<>();
        }
        size = 0;
    }

    public void put(K key, V value) {
        if (key == null)
            throw new IllegalArgumentException("Key cannot be null.");

        int index = hash(key);
        List<Entry<K, V>> bucket = buckets[index];

        for (Entry<K, V> entry : bucket) {
            if (entry.key.equals(key)) {
                entry.value = value;
                return;
            }
        }
        bucket.add(new Entry<>(key, value));
        size++;
    }

    public V get(K key) {
        int index = hash(key);
        List<Entry<K, V>> bucket = buckets[index];

        for (Entry<K, V> entry : bucket) {
            if (entry.key.equals(key)) {
                return entry.value;
            }
        }

        return null;
    }

    public void remove(K key) {
        int index = hash(key);
        List<Entry<K, V>> bucket = buckets[index];

        for (Entry<K, V> entry : bucket) {
            if (entry.key.equals(key)) {
                bucket.remove(entry);
                size--;
                return;
            }
        }
    }
    public int size() {
        return size;
    }

    private int hash(K key) {
        return key.hashCode() % buckets.length;
    }


    private static class Entry<K, V> {
        K key;
        V value;

        public Entry(K key, V value) {
            this.key = key;
            this.value = value;
        }
    }
    public static void testSystemMap(){
        System.out.println("TEST SYSTEM MAP ");
        long startTime, endTime;

        HashMap<Integer, String> hashMap = new HashMap<>();
        startTime = System.currentTimeMillis();

        // Insert VALUE elements
        for (int i = 0; i < VALUE; i++) {
            hashMap.put(i, "Value" + i);
        }

        endTime = System.currentTimeMillis();
        System.out.println("Insertion time: " + (endTime - startTime) + " ms");

        startTime = System.currentTimeMillis();
        // Search for VALUE elements
        for (int i = 0; i < VALUE; i++) {
            hashMap.get(i);
        }
        endTime = System.currentTimeMillis();
        System.out.println("Search time: " + (endTime - startTime) + " ms");
        startTime = System.currentTimeMillis();
        // Remove POTRION elements
        for (int i = 0; i < POTRION; i++) {
            hashMap.remove(i);
        }
        endTime = System.currentTimeMillis();
        System.out.println("Deletion time: " + (endTime - startTime) + " ms");

        System.out.println("Final size of the map: " + hashMap.size());
    }
    public static void testMyMap(){
        System.out.println("TEST MY MAP ");
        long startTime, endTime;

        myMAP<Integer, String> hashMap = new myMAP<>();
        startTime = System.currentTimeMillis();

        // Insert VALUE elements
        for (int i = 0; i < VALUE; i++) {
            hashMap.put(i, "Value" + i);
        }

        endTime = System.currentTimeMillis();
        System.out.println("Insertion time: " + (endTime - startTime) + " ms");

        startTime = System.currentTimeMillis();
        // Search for VALUE elements
        for (int i = 0; i < VALUE; i++) {
            hashMap.get(i);
        }
        endTime = System.currentTimeMillis();
        System.out.println("Search time: " + (endTime - startTime) + " ms");

        startTime = System.currentTimeMillis();
        // Remove POTRION elements
        for (int i = 0; i < POTRION; i++) {
            hashMap.remove(i);
        }
        endTime = System.currentTimeMillis();
        System.out.println("Deletion time: " + (endTime - startTime) + " ms");

        System.out.println("Final size of the map: " + hashMap.size());
    }
    public static void main(String[] args) {
        System.out.println("添加元素总数为： " + VALUE);
        System.out.println("删除元素总数为： " + POTRION);
        testSystemMap();
        testMyMap();
    }
}
